package com.guoguo.api;

import java.io.BufferedReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.guoguo.base.BaseController;
import com.guoguo.base.StaticResource;
import com.guoguo.entity.Album;
import com.guoguo.entity.Attention;
import com.guoguo.entity.Buys;
import com.guoguo.entity.Orders;
import com.guoguo.entity.UserExt;
import com.guoguo.entity.vo.AlbumsVO;
import com.guoguo.enums.PayEnum;
import com.guoguo.service.AlbumService;
import com.guoguo.service.BuysService;
import com.guoguo.service.IPayService;
import com.guoguo.service.IUserExtService;
import com.guoguo.utils.JsonUtils;
import com.guoguo.utils.PropertyUtils;
import com.guoguo.utils.RedisUtils;
import com.guoguo.utils.nowpay.HttpUtil;
import com.guoguo.utils.nowpay.Md5Util;

/**
 * Created by Administrator on 2017/10/23 0023.
 */

     /*
                           _ooOoo_
                          o8888888o
                          88" . "88
                          (| -_- |)
                          O\  =  /O
                       ____/`---'\____
                     .'  \\|     |//  `.
                    /  \\|||  :  |||//  \
                   /  _||||| -:- |||||-  \
                   |   | \\\  -  /// |   |
                   | \_|  ''\---/''  |   |
                   \  .-\__  `-`  ___/-. /
                 ___`. .'  /--.--\  `. . __
              ."" '<  `.___\_<|>_/___.'  >'"".
             | | :  `- \`.;`\ _ /`;.`/ - ` : | |
             \  \ `-.   \_ __\ /__ _/   .-` /  /
        ======`-.____`-.___\_____/___.-`____.-'======
                           `=---='
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                 佛祖保佑       永无BUG
        */
@RestController
@RequestMapping("/api/pay")
public class PayController extends BaseController {
	private final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(PayController.class);

	@Autowired
	private IUserExtService iUserExtService;

	@Autowired
	private IPayService iPayService;

	@Autowired
	private BuysService buysService;

	@Autowired
	private AlbumService albumService;
	
	/**
	 * 解锁专辑
	 *
	 * @param userId
	 * @param albId
	 * @param payType
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/unlocked", method = RequestMethod.POST)
	public JSONObject unlocked(@RequestParam String userId, @RequestParam String albId, @RequestParam int payType) {
		if (payType == PayEnum.PAY_TYPE_RECHARGE.getId() || payType == PayEnum.PAY_TYPE_MEMBER.getId()) {
			return returnResult(PayEnum.PAY_PAYMENT_TYPE.getId(), "", PayEnum.PAY_PAYMENT_TYPE.getValue());
		}
		Album album = albumService.selectByPrimaryKey(albId);
		// 验证用户积分
		UserExt userExt = iUserExtService.findUserExt(userId);
		if (userExt != null && album != null) {
			// 积分大于等于现价
			BigDecimal presentPrice = BigDecimal.valueOf(Double.valueOf(album.getPresentPrice() == null ? "0" : album.getPresentPrice()));
			// TODO: 2017/10/24 0024 只有当消费的时候，才会根据不同的支付类型从用户帐户里获取不同的余额
			BigDecimal userOver = null;
			if (payType == PayEnum.PAY_TYPE_POINT.getId()) {
				userOver = new BigDecimal(userExt.getPoint());
			} else if (payType == PayEnum.PAY_TYPE_MONEY.getId()) {
				userOver = new BigDecimal(userExt.getMoney());
			}
			// TODO: 2017/10/24 0024 帐户余额与专辑现价进行比较，只有当余额大于等于现价，才能进行下一步操作
			if (userOver.compareTo(presentPrice) >= 0) {
				// 创建订单记录
				Orders orders = iPayService.createOrder(payType, userId);
				// 创建订单不为空才继续创建消费明细及解锁记录
				if (orders != null) {
					// 创建明细记录
					int num = iPayService.createPayJournal(payType, orders.getOrderNo(), albId, presentPrice.toString());
					if (num <= 0) {
						return returnResult(PayEnum.PAY_FLOW_ERROR.getId(), "", PayEnum.PAY_FLOW_ERROR.getValue());
					}

					// 创建解锁记录
					Buys buys = buysService.saveBus(userId, orders.getOrderNo(), albId);
					if (buys == null) {
						return returnResult(PayEnum.PAY_BUYS_ERROR.getId(), "", PayEnum.PAY_BUYS_ERROR.getValue());
					}
				} else {
					return returnResult(PayEnum.PAY_ORDER_ERROR.getId(), "", PayEnum.PAY_ORDER_ERROR.getValue());
				}

				// 更新用户信息
				BigDecimal point = null;
				if (presentPrice != null) {
					userExt.setIcon(null);
					// TODO: 2017/10/24 0024 根据不同的消费支付方式，修改用户不同的帐户余额
					if (payType == PayEnum.PAY_TYPE_POINT.getId()) {
						point = new BigDecimal(userExt.getPoint());
						userExt.setPoint(point.subtract(presentPrice).longValue());
					} else if (payType == PayEnum.PAY_TYPE_MONEY.getId()) {
						point = new BigDecimal(userExt.getMoney());
						userExt.setMoney(point.subtract(presentPrice).doubleValue());
					}
					UserExt userExt1 = iUserExtService.updateUserExt(userExt);
					if (null == userExt1) {
						return returnResult(PayEnum.PAY_USER_EXT_ERROR.getId(), "", PayEnum.PAY_USER_EXT_ERROR.getValue());
					}
				} else {
					return returnResult(PayEnum.PAY_ORDER_ERROR.getId(), "", PayEnum.PAY_ORDER_ERROR.getValue());
				}

			} else {
				return returnResult(PayEnum.PAY_POINT_LACK.getId(), "", PayEnum.PAY_POINT_LACK.getValue());
			}

		} else {
			return returnResult(PayEnum.PAY_ARGS_ERROR.getId(), "", PayEnum.PAY_ARGS_ERROR.getValue());
		}

		return returnResult(PayEnum.PAY_SUCCESS.getId(), "", PayEnum.PAY_SUCCESS.getValue());
	}

	/**
	 * 创建订单
	 *
	 * @param userId
	 * @param payType
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/payReady", method = RequestMethod.POST)
	public JSONObject payReady(@RequestParam String userId, @RequestParam int payType) {
		Orders orders = iPayService.createOrder(payType, userId);
		return returnResult(200, orders, "");
	}

	/**
	 * 支付回调
	 *
	 * @param userId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/recharge", method = RequestMethod.POST)
	public JSONObject recharge(@RequestParam String userId, @RequestParam String rechargeId, @RequestParam int payType) {
		UserExt userExt = iUserExtService.findUserExt(userId);
		iPayService.payCallBack(rechargeId, payType, userExt);
		return returnResult(200, "", "");
	}

	/**
	 * 获取专辑及用户的相关信息 isfirst：用户是否首充 isAtten：用户是否关注 isUnlock：用户是否解锁
	 *
	 * @param userId
	 * @param albId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/albumUserInfo", method = RequestMethod.POST)
	public JSONObject albumUserInfo(@RequestParam String userId, @RequestParam String albId) {
		Map<String, Object> data = new HashedMap();
		List<Orders> orderses = iPayService.getOrderList(userId);
		Map<String, String> par = new HashedMap();
		par.put("userId", userId);
		par.put("albId", albId);
		Attention attention = iUserExtService.findUserAttention(par);

		Buys buys = new Buys();
		buys.setUserId(userId);
		buys.setAlbId(albId);
		List<Buys> buyses = buysService.getUserBuys(buys);

		data.put("isfirst", orderses.size() > 0 ? false : true);
		data.put("isAtten", attention == null ? false : true);
		data.put("isUnlock", buyses.size() > 0 ? true : false);

		return returnResult(200, data, "");
	}

	/**
	 * 获取所有支付方式
	 *
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/rechargeList", method = RequestMethod.POST)
	public JSONObject recharge(@RequestParam String userId, @RequestParam String albId) {
		RedisUtils redisUtils = RedisUtils.getInstance();
		Map<String, Object> data = new HashedMap();
		if (redisUtils.exists(StaticResource.SYS_INIT_RECHARGE_KEY)) {
			// 获取所有的支付类型
			Map<String, String> rechargeMap = redisUtils.hgetall(StaticResource.SYS_INIT_RECHARGE_KEY);
			List<JSONObject> rechargeList = new ArrayList();
			List<JSONObject> memberList = new ArrayList();

			Set<String> keys = rechargeMap.keySet();
			for (String key : keys) {
				JSONObject rechargeJson = JSONObject.parseObject(rechargeMap.get(key));
				int rechType = rechargeJson.getIntValue("rechType");
				if (rechType == 0) {
					rechargeList.add(rechargeJson);
				}
				if (rechType == 1) {
					memberList.add(rechargeJson);
				}
			}

			data.put("recharge", rechargeList);
			data.put("member", memberList);
		}

		return returnResult(200, data, "");
	}

	private static String createFormString(Map<String, String> para, boolean sort, boolean encode) {
		List<String> keys = new ArrayList<String>(para.keySet());
		if (sort) {
			Collections.sort(keys);
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = para.get(key);
			if (encode) {
				try {
					value = URLEncoder.encode(value, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
			if (i == keys.size() - 1) {
				sb.append(key).append("=").append(value);
			} else {
				sb.append(key).append("=").append(value).append("&");
			}
		}
		return sb.toString();
	}

	/**
	 * 请求生成商户订单
	 *
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/createPayOrder", method = RequestMethod.POST)
	public JSONObject createPayOrder(@RequestParam Map<String, String> model) {
		logger.info("into PayController creatPayOrder method");
		Map<String, String> data = new HashMap<String, String>();
		Map<String, String> resultData = new HashMap<String, String>();
		String needcheckmsgOldN = null;
		String needcheckmsgOld = null;
		String needcheckmsg = null;
		Integer needcheckmsgAccount = null;
		String consumerId = model.get("consumerId");// 消费者Id
		String mhtOrderType = model.get("mhtOrderType");// 商户交易类型
		String mhtOrderName = model.get("mhtOrderName");// 商户商品名称
		String mhtOrderAmt = model.get("mhtOrderAmt");// 商户订单交易金额
		String mhtOrderDetail = model.get("mhtOrderDetail");// 商户订单详情
		String mhtOrderTimeOut = model.get("mhtOrderTimeOut");// 商户订单超时时间
		String mhtOrderStartTime = model.get("mhtOrderStartTime");// 商户订单开始时间
		String payChannelType = model.get("payChannelType");// 用户所选渠道类型

		try {
			if(StringUtils.isNotBlank(mhtOrderName) && !mhtOrderName.equals("null")){
				AlbumsVO albumsVO = new AlbumsVO();
				albumsVO = albumService.selectByPrimaryKey(mhtOrderName);
				if(albumsVO != null && StringUtils.isNotBlank(albumsVO.getPresentPrice())){
					mhtOrderAmt = albumsVO.getPresentPrice();
				}
			}
			data = iPayService.creatPayOrder(mhtOrderType, mhtOrderName, mhtOrderAmt, mhtOrderDetail, mhtOrderTimeOut, mhtOrderStartTime, consumerId);
			data.put("funcode", "WP001");// 功能码
			data.put("version", "1.0.0");// 版本号
			data.put("deviceType", "01");// 设备类型
			data.put("mhtCharset", "UTF-8");// 商户字符编码
			data.put("mhtSignType", "MD5");// 商户的签名方法
			data.put("deviceType", "01");// 设备类型
			data.put("mhtCurrencyType", model.get("mhtCurrencyType"));// 订单币种类型
			data.put("mhtOrderName", mhtOrderName);// 商户商品名称
			data.put("mhtOrderAmt", mhtOrderAmt);// 商户订单交易金额
			data.put("mhtOrderDetail", mhtOrderDetail);// 商户订单详情
			data.put("mhtOrderStartTime", mhtOrderStartTime);// 商户订单开始时间
			data.put("mhtOrderTimeOut", mhtOrderTimeOut);// 商户订单超时时间
			data.put("mhtOrderType", mhtOrderType);// 商户交易类型
			data.put("mhtReserved", "666");// 商户保留域
			data.put("payChannelType", payChannelType);// 用户所选渠道类型
			data.put("mhtLimitPay", model.get("mhtLimitPay"));// 是否支持信用卡支付
			data.put("notifyUrl", PropertyUtils.getProperty("api.properties", "api.domainName") + "api/pay/createPayMessage/");// 商户后台通知URL
			if (payChannelType.equals("13")) {
				data.put("appId", PropertyUtils.getProperty("api.properties", "api.wxpay.appId"));// 商户应用唯一标识微信
			} else if (payChannelType.equals("12")) {
				data.put("appId", PropertyUtils.getProperty("api.properties", "api.alipay.appId"));// 商户应用唯一标识支付宝
			}
			String preSignStr = createFormString(data, true, false);
			if (payChannelType.equals("13")) {
				needcheckmsgOldN = Md5Util.md5(preSignStr + "&" + Md5Util.md5(PropertyUtils.getProperty("api.properties", "api.wxpay.mKey")));// 0nqIDgkOnNBD6qoqO5U68RO1fNqiaisg
			} else if (payChannelType.equals("12")) {
				needcheckmsgOldN = Md5Util.md5(preSignStr + "&" + Md5Util.md5(PropertyUtils.getProperty("api.properties", "api.alipay.mKey")));// 0nqIDgkOnNBD6qoqO5U68RO1fNqiaisg
			}
			needcheckmsgOld = "mhtSignature=" + needcheckmsgOldN;
			needcheckmsg = preSignStr + "&" + needcheckmsgOld;
			resultData.put("needcheckmsg", needcheckmsg);
			resultData.put("mhtOrderNo", data.get("mhtOrderNo"));
			needcheckmsgAccount = iPayService.updateNeedcheckmsg(data.get("mhtOrderNo"), needcheckmsgOldN);
			if (needcheckmsgAccount > 0) {
				return JsonUtils.returnObject(200, resultData, "true");
			} else {
				return JsonUtils.returnObject(201, null, "更新报文数据失败");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return JsonUtils.returnObject(201, null, "false");
		}
	}

	/**
	 * 通知商户支付结果
	 * 
	 * @param model
	 */
	@ResponseBody
	@RequestMapping(value = "/createPayMessage", method = RequestMethod.POST)
	private String createPayMessage(@RequestParam Map<String, String> model, HttpServletRequest request) {
		logger.info("into PayController creatPayMessage method  ****************************************************************");
		/*Map<String, String> data = new HashMap<String, String>();*/
		String resultData = null;
		boolean isSuccess = false;
		String payTime = null;
		String mhtOrderNo = null;
		String nowPayOrderNo = null;
		String channelOrderNo = null;
		/*data.put("funcode", "N001");// 功能码
		data.put("version", "1.0.0");// 版本号
		data.put("deviceType", "01");// 设备类型
		data.put("mhtCharset", "UTF-8");// 商户字符编码
		data.put("mhtSignType", "MD5");// 商户的签名方法
		data.put("mhtOrderNo", model.get("mhtOrderNo"));// 商户订单号
		data.put("mhtCurrencyType", model.get("mhtCurrencyType"));// 订单币种类型
		data.put("mhtOrderAmt", model.get("mhtOrderAmt"));// 商户订单交易金额
		data.put("mhtOrderName", model.get("mhtOrderName"));// 商户商品名称
		data.put("mhtOrderDetail", model.get("mhtOrderDetail"));// 商户订单详情
		data.put("mhtOrderStartTime", model.get("mhtOrderStartTime"));// 商户订单开始时间
		data.put("mhtOrderTimeOut", model.get("mhtOrderTimeOut"));// 商户订单超时时间
		data.put("payTime", model.get("payTime"));// 支付成功时间
		data.put("mhtOrderType", model.get("mhtOrderType"));// 商户交易类型
		data.put("mhtReserved", "666");// 商户保留域
		data.put("payChannelType", model.get("payChannelType"));// 用户所选渠道类型
		data.put("mhtSubAppId", model.get("mhtSubAppId"));// 商户的appId
		data.put("appId", PropertyUtils.getProperty("api.properties", "api.pay.appId"));// 商户应用唯一标识
		data.put("mhtLimitPay", model.get("mhtLimitPay"));// 是否支持信用卡支付
		data.put("nowPayOrderNo", model.get("nowPayOrderNo"));// 现在支付流水号
		data.put("channelOrderNo", model.get("channelOrderNo"));// 渠道订单号
		data.put("tradeStatus", model.get("tradeStatus"));// 交易支付状态
		data.put("payConsumerId", model.get("payConsumerId"));// 付款人账号
		data.put("payConsumerName", model.get("payConsumerName"));// 付款人用户名
		data.put("mhtSignature", model.get("mhtSignature"));// 数据签名
*/		try {
			// 获取通知数据需要从body中流式读取
			BufferedReader reader = request.getReader();
			StringBuilder reportBuilder = new StringBuilder();
			String tempStr = "";
			while ((tempStr = reader.readLine()) != null) {
				reportBuilder.append(tempStr);
			}
			// 报文数据字符串
			String reportContent = reportBuilder.toString();
			List<String> result = Arrays.asList(StringUtils.split(reportContent, "&"));
			for (String string : result) {
				if (string.contains("mhtOrderNo")) {
					mhtOrderNo = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("payTime")) {
					payTime = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("nowPayOrderNo")) {
					nowPayOrderNo = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("channelOrderNo")) {
					channelOrderNo = string.substring(string.indexOf("=") + 1, string.length());
				}
			}
			if (result.size() > 0 && result != null) {
				if (result.contains("tradeStatus=A001")) {
					isSuccess = iPayService.creatPayMessageNoti(mhtOrderNo, "0", payTime, nowPayOrderNo, channelOrderNo);
					if (isSuccess) {
						resultData = "success=Y";// 通知成功
					} else {
						resultData = "success=N";// 通知失败
					}
				} else {
					resultData = "success=N";// 通知失败
				}
			} else {
				resultData = "success=N";// 通知失败
			}
			return resultData;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return resultData = "success=N";// 通知失败
		}
	}

	/**
	 * 查询实际支付结果
	 * 
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/selectPayOrder", method = RequestMethod.POST)
	public JSONObject selectPayOrder(@RequestParam Map<String, String> model, HttpServletRequest request) {
		logger.info("into PayController selectPayOrder method");
		Map<String, String> data = new HashMap<String, String>();
		Map<String, String> resultData = new HashMap<String, String>();
		boolean isSuccess = false;
		String payUrl = null;
		String needcheckmsgOldN = null;
		String needcheckmsgOld = null;
		String needcheckmsg = null;
		String tempStr = null;
		String payTime = null;
		String nowPayOrderNo = null;
		String channelOrderNo = null;
		String mhtOrderAmt = null;
		data.put("funcode", "MQ002");// 功能码
		data.put("version", "1.0.0");// 版本号
		data.put("deviceType", "01");// 设备类型
		// data.put("appId", model.get("appId"));//商户应用唯一标识
		String payChannelType = model.get("payChannelType");// 用户所选渠道类型
		data.put("mhtOrderNo", model.get("mhtOrderNo"));// 商户的订单号
		data.put("mhtCharset", "UTF-8");// 商户字符编码
		data.put("mhtSignType", "MD5");// 商户的签名方法
		try {
			payUrl = PropertyUtils.getProperty("api.properties", "api.payUrl.url");
			if (payChannelType.equals("13")) {
				data.put("appId", PropertyUtils.getProperty("api.properties", "api.wxpay.appId"));// 商户应用唯一标识微信
			} else if (payChannelType.equals("12")) {
				data.put("appId", PropertyUtils.getProperty("api.properties", "api.alipay.appId"));// 商户应用唯一标识支付宝
			}
			String preSignStr = createFormString(data, true, false);
			if (payChannelType.equals("13")) {
				needcheckmsgOldN = Md5Util.md5(preSignStr + "&" + Md5Util.md5(PropertyUtils.getProperty("api.properties", "api.wxpay.mKey")));// 0nqIDgkOnNBD6qoqO5U68RO1fNqiaisg
			} else if (payChannelType.equals("12")) {
				needcheckmsgOldN = Md5Util.md5(preSignStr + "&" + Md5Util.md5(PropertyUtils.getProperty("api.properties", "api.alipay.mKey")));// 0nqIDgkOnNBD6qoqO5U68RO1fNqiaisg
			}
			needcheckmsgOld = "mhtSignature=" + needcheckmsgOldN;
			needcheckmsg = preSignStr + "&" + needcheckmsgOld;
			tempStr = HttpUtil.post(payUrl, needcheckmsg);
			// 获取通知数据需要从body中流式读取
			// BufferedReader reader = request.getReader();
			// StringBuilder reportBuilder = new StringBuilder();
			// while((tempStr = reader.readLine()) != null){
			// reportBuilder.append(tempStr);
			// }
			// 报文数据字符串
			String reportContent = tempStr.toString();
			List<String> result = Arrays.asList(StringUtils.split(reportContent, "&"));
			for (String string : result) {
				if (string.contains("payTime")) {
					payTime = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("nowPayOrderNo")) {
					nowPayOrderNo = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("channelOrderNo")) {
					channelOrderNo = string.substring(string.indexOf("=") + 1, string.length());
				}
				if (string.contains("mhtOrderAmt")) {
					mhtOrderAmt = string.substring(string.indexOf("=") + 1, string.length());
				}
			}
			if (result.size() > 0 && result != null) {
				if (result.contains("tradeStatus=A001") && result.contains("responseCode=A001")) {
					isSuccess = iPayService.creatPayMessage(model.get("mhtOrderNo"), "1", payTime, nowPayOrderNo, channelOrderNo,mhtOrderAmt);
					if (isSuccess) {
						resultData.put("success", "Y");// 支付成功
					} else {
						resultData.put("success", "N");// 支付失败
					}
				} else {
					resultData.put("success", "N");// 支付失败
				}
			} else {
				resultData.put("success", "N");// 支付失败
			}
			return JsonUtils.returnObject(200, resultData, "true");
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return JsonUtils.returnObject(201, null, "false");
		}
	}

}
